package org.springblade.modules.repair.service.approve;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.config.ProjectApiConfiguration;
import org.springblade.common.constant.BaseRoleConstant;
import org.springblade.common.constant.MaintenanceSmsConstant;
import org.springblade.common.constant.TemplateMsgConstant;
import org.springblade.common.utils.AsyncHttpUtil;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.sms.model.SmsResponse;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.SpringUtil;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.core.tool.utils.WebUtil;
import org.springblade.modules.repair.dto.PlanLogDTO;
import org.springblade.modules.repair.entity.*;
import org.springblade.modules.repair.enums.*;
import org.springblade.modules.repair.service.*;
import org.springblade.modules.repair.service.approve.strategy.ApproveBusinessFlow;
import org.springblade.modules.repair.vo.BusinessApproveVO;
import org.springblade.modules.repair.vo.ElevatorSimpleInfoVO;
import org.springblade.modules.resource.utils.SmsUtil;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.vo.SimpleUserVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.TransactionStatus;

import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 配件申请流程
 * @Author ysq
 * @Date 2024/05/17
 **/
@Slf4j
public class PartsFlow implements ApproveBusinessFlow {

	private final IMaintainMalfunctionLogService malfunctionLogService = SpringUtil.getBean(IMaintainMalfunctionLogService.class);
	private final IElevatorPartsStructureRelationService elevatorPartsStructureRelationService = SpringUtil.getBean(IElevatorPartsStructureRelationService.class);
	private final MaintainPartsWorkService maintainPartsWorkService = SpringUtil.getBean(MaintainPartsWorkService.class);
	private final MaintainMsgService msgService = SpringUtil.getBean(MaintainMsgService.class);
	private final AsyncHttpUtil asyncHttpUtil = SpringUtil.getBean(AsyncHttpUtil.class);
	private final MaintainPartsWorkSkuService partsWorkSkuService = SpringUtil.getBean(MaintainPartsWorkSkuService.class);

	@Override
	public boolean addApprove(BusinessApproveVO businessApprove) {
		// 手动开启事务
		TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
		try {
			// 查询技术支持审批人
			List<SimpleUserVO> approveUsers = userService.getUserByDeptIdsAndRoleAlias(AuthUtil.getDeptId(), BaseRoleConstant.TECHNICAL_SUPPORT);
			// 判断是否有审批人
			boolean isHasApproveUser = Func.isNotEmpty(approveUsers);
			if (isHasApproveUser) {
				businessApprove.setApproveIds(approveUsers.stream().map(t -> String.valueOf(t.getUserId())).collect(Collectors.joining(",")));
				businessApprove.setApproveName(approveUsers.stream().map(t -> t.getUserName()).collect(Collectors.joining(",")));
			}
			boolean result = businessApproveService.saveOrUpdate(businessApprove);

			if (result) {
				if (isHasApproveUser) {
					// 插入任务追踪记录
					malfunctionLogService.insertWorkLog(businessApprove.getWorkOrderId(), TaskStatusEnum.PARTS_APPLY.getName(), TaskStatusEnum.PARTS_APPLY.getStatus(), null, AuthUtil.getUserId(), "技术支持",
						approveUsers.stream().map(t -> String.valueOf(t.getUserName())).collect(Collectors.joining("、")));
					// 发送消息通知
					MaintainPartsWork maintainPartsWork = maintainPartsWorkService.getOne(Wrappers.<MaintainPartsWork>lambdaQuery().eq(MaintainPartsWork::getPlanId, businessApprove.getWorkOrderId()), false);
					ElevatorSimpleInfoVO elevatorInfo = maintainPlanContentService.getElevatorSimpleInfo(businessApprove.getWorkOrderId());
					// 跳转链接
					String skipUrl = String.format("subpages/approve/partApprovalDetail?type=2&id=%s", businessApprove.getWorkOrderId());
					Map<String, String> templateDataMap = new HashMap<>(8);
					templateDataMap.put("first", "报修审批提醒");
					templateDataMap.put("keyword1", elevatorInfo.getBuildingName() + elevatorInfo.getElevatorAddress());
					String partsName = maintainPartsWork.getPartsName().split("&amp;&amp;")[maintainPartsWork.getPartsName().split("&amp;&amp;").length - 1];
					templateDataMap.put("keyword2", String.format("%s, 数量： %d个", partsName, maintainPartsWork.getNum()));
					templateDataMap.put("keyword3", maintainPartsWork.getDesc());
					User applyUser = userService.getById(AuthUtil.getUserId());
					templateDataMap.put("keyword4", String.format("%s%s", applyUser.getRealName(), applyUser.getPhone()));
					templateDataMap.put("keyword5", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm"));
					templateDataMap.put("remark", "请尽快审核!");
					templateDataMap.put("params", skipUrl);
					for (SimpleUserVO approveUser : approveUsers) {
						if (Func.isNotEmpty(approveUser.getOpenid())) {
							log.info("===========给技术支持发送模板消息,审批人:[{}]===========", approveUser.getUserName());
							weChatDialogueService.sendMsg(approveUser.getOpenid(), TemplateMsgConstant.T_REPAIR_APPROVE_ID, templateDataMap);
						}

						log.info("===========给技术支持发送短信,审批人:[{}], 手机号码:[{}]===========", approveUser.getUserName(), approveUser.getPhone());
						Map<String, String> smsParam = new HashMap<>(2);
						smsParam.put("status", "【待审批】");
						smsParam.put("pageLocation", "【配件审批】");
						SmsResponse smsResponse = SmsUtil.sendMessage(MaintenanceSmsConstant.TASK_PROGRESS, BladeConstant.ADMIN_TENANT_ID, smsParam, approveUser.getPhone());
						log.info("===========给技术支持发送短信,结果:[{}]===========", JSONUtil.toJsonStr(smsResponse));
					}
				} else {
					// 插入任务追踪记录
					malfunctionLogService.insertWorkLog(businessApprove.getWorkOrderId(), TaskStatusEnum.PARTS_APPLY.getName(), TaskStatusEnum.PARTS_APPLY.getStatus(), null, AuthUtil.getUserId(), "技术支持", "未设置审批人");
					// 没有审批人，直接通过->信息审核
					businessApprove.setApproveStatus(ApproveStatusEnum.PASSED.getId());
					businessApprove.setSkip(true);
					this.approve(businessApprove);
				}
			}

		} catch (Exception e) {
			platformTransactionManager.rollback(transactionStatus);
			throw new ServiceException("报障失败: " + e.getMessage());
		}

		platformTransactionManager.commit(transactionStatus);
		return true;
	}

	@Override
	public boolean approve(BusinessApproveVO businessApproveVO) {
		BusinessApprove businessApprove = businessApproveService.getById(businessApproveVO.getId());
		if (Func.isEmpty(businessApprove)) {
			throw new ServiceException("未找到相关流程!");
		}

		// 手动开启事务
		TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
		// 查询工单
		MaintainPlanContent maintainPlanContent = maintainPlanContentService.getById(businessApprove.getWorkOrderId());
		if (maintainPlanContent == null) {
			throw new ServiceException("工单不存在");
		}
		int curOrderStatus = maintainPlanContent.getStatus();
		if (curOrderStatus != TaskStatusEnum.PARTS_APPLY.getStatus() && curOrderStatus != TaskStatusEnum.PARTS_APPROVE.getStatus()) {
			throw new ServiceException("流程已审批，不能重复审批");
		}

		try {
			switch (ApproveStatusEnum.getByStatus(businessApproveVO.getApproveStatus())) {
				// 通过
				case PASSED: {
					// 需求审批
					if (curOrderStatus == TaskStatusEnum.PARTS_APPLY.getStatus()) {
						if (!businessApproveVO.isSkip()) {
							// 更新任务追踪记录
							MaintainMalfunctionLog applyNodeLog = malfunctionLogService.getOne(Wrappers.<MaintainMalfunctionLog>lambdaQuery().eq(MaintainMalfunctionLog::getPlanId, maintainPlanContent.getId()).eq(MaintainMalfunctionLog::getPlanStatus, TaskStatusEnum.PARTS_APPLY.getStatus()).orderByDesc(MaintainMalfunctionLog::getId), false);
							if (applyNodeLog != null) {
								applyNodeLog.setUserNames(AuthUtil.getNickName());
								// 插入任务记录
								PlanLogDTO planLogDTO = new PlanLogDTO();
								planLogDTO.setExpDesc(String.valueOf(businessApproveVO.getRemark()));
								applyNodeLog.setExt(JSONObject.toJSONString(planLogDTO));
								malfunctionLogService.updateById(applyNodeLog);
							}
						}
						// 查询执行采购审批人
						List<SimpleUserVO> approveUsers = userService.getUserByRoleAlias(BaseRoleConstant.EXECUTION_PURCHASER, AuthUtil.getTenantId());
						// 判断是否有审批人
						boolean isHasApproveUser = Func.isNotEmpty(approveUsers);
						LambdaUpdateWrapper<BusinessApprove> updateWrapper = Wrappers.<BusinessApprove>lambdaUpdate()
							.eq(BusinessApprove::getId, businessApprove.getId())
							.set(BusinessApprove::getApproveStatus, ApproveStatusEnum.PENDING.getId())
							.set(BusinessApprove::getRemark, businessApproveVO.getRemark());
						if (isHasApproveUser) {
							updateWrapper.set(BusinessApprove::getApproveIds, approveUsers.stream().map(t -> String.valueOf(t.getUserId())).collect(Collectors.joining(",")))
								.set(BusinessApprove::getApproveName, approveUsers.stream().map(t -> t.getUserName()).collect(Collectors.joining(",")));
							// 插入任务追踪记录
							malfunctionLogService.insertWorkLog(maintainPlanContent.getId(), TaskStatusEnum.PARTS_APPROVE.getName(), TaskStatusEnum.PARTS_APPROVE.getStatus(), null, AuthUtil.getUserId(), "执行采购",
								approveUsers.stream().map(t -> t.getUserName()).collect(Collectors.joining("、")));
						} else {
							updateWrapper.set(BusinessApprove::getApproveIds, null).set(BusinessApprove::getApproveName, null);
							// 插入任务追踪记录
							malfunctionLogService.insertWorkLog(maintainPlanContent.getId(), TaskStatusEnum.PARTS_APPROVE.getName(), TaskStatusEnum.PARTS_APPROVE.getStatus(), null, AuthUtil.getUserId(), "执行采购", "未设置审批人");
						}
						// 更新审批信息
						businessApproveService.update(updateWrapper);
						// 更新工单状态：1->信息审核
						maintainPlanContent.setStatus(TaskStatusEnum.PARTS_APPROVE.getStatus());
						maintainPlanContentService.updateById(maintainPlanContent);

						// 发送通知
						if (isHasApproveUser) {
							ElevatorSimpleInfoVO elevatorInfo = maintainPlanContentService.getElevatorSimpleInfo(businessApprove.getWorkOrderId());
							log.info("===========发送信息审核web消息===========");
							MaintainMsg maintainMsg = new MaintainMsg();
							maintainMsg.setTitle(String.format("%s-%s", elevatorInfo.getBuildingName(), elevatorInfo.getElevatorAddress()));
							maintainMsg.setContent("您有【信息审核】待审核处理");
							maintainMsg.setType(MsgTypeEnum.PARTS_MSG_APPROVE.getId());
							maintainMsg.setOtherId(businessApprove.getWorkOrderId());
							msgService.sendWebMsg(maintainMsg, approveUsers.stream().map(t -> t.getUserId()).collect(Collectors.toList()));

							for (SimpleUserVO approveUser : approveUsers) {
								log.info("===========给执行采购发送短信,审批人:[{}], 手机号码:[{}]===========", approveUser.getUserName(), approveUser.getPhone());
								Map<String, String> smsParam = new HashMap<>(2);
								smsParam.put("taskName", "配件任务【信息审核】");
								SmsUtil.sendMessage(MaintenanceSmsConstant.MAINTAIN_AUDIT, BladeConstant.ADMIN_TENANT_ID, smsParam, approveUser.getPhone());
							}
						}
						break;
					} else {
						// 更新任务追踪记录
						MaintainMalfunctionLog approveNodeLog = malfunctionLogService.getOne(Wrappers.<MaintainMalfunctionLog>lambdaQuery().eq(MaintainMalfunctionLog::getPlanId, maintainPlanContent.getId()).eq(MaintainMalfunctionLog::getPlanStatus, TaskStatusEnum.PARTS_APPROVE.getStatus()).orderByDesc(MaintainMalfunctionLog::getId), false);
						if (approveNodeLog != null) {
							approveNodeLog.setUserNames(AuthUtil.getNickName());
							PlanLogDTO planLogDTO = new PlanLogDTO();
							planLogDTO.setExpDesc(String.valueOf(businessApproveVO.getRemark()));
							approveNodeLog.setExt(JSONObject.toJSONString(planLogDTO));
							malfunctionLogService.updateById(approveNodeLog);
						}
						// 信息审核
						malfunctionLogService.insertWorkLog(maintainPlanContent.getId(), TaskStatusEnum.PARTS_OFFER.getName(), TaskStatusEnum.PARTS_OFFER.getStatus(), null, AuthUtil.getUserId(), "商务");
						businessApprove.setApproveStatus(ApproveStatusEnum.PASSED.getId());
						businessApprove.setRemark(businessApproveVO.getRemark());
						// 更新审批信息
						businessApproveService.updateById(businessApprove);
						// 更新工单状态：2->销售生单
						maintainPlanContent.setStatus(TaskStatusEnum.PARTS_OFFER.getStatus());
						maintainPlanContentService.updateById(maintainPlanContent);
						// 更新配件详情信息
						List<MaintainPartsWork> maintainPartsWorks = maintainPartsWorkService.list(Wrappers.<MaintainPartsWork>lambdaQuery().eq(MaintainPartsWork::getPlanId, maintainPlanContent.getId()));
						if (maintainPartsWorks == null) {
							throw new ServiceException("配件工单明细不存在");
						}
						if (Func.isEmpty(businessApproveVO.getSkuList())) {
							throw new ServiceException("未关联sku信息，请关联sku信息后再审批");
						}
						List<Long> partsSkuIds = businessApproveVO.getSkuList().stream().map(MaintainPartsWorkSku::getId).collect(Collectors.toList());
						List<Long> workId = maintainPartsWorks.stream().map(MaintainPartsWork::getId).collect(Collectors.toList());
						if(Func.isNotEmpty(partsSkuIds)){
							partsWorkSkuService.remove(Wrappers.<MaintainPartsWorkSku>lambdaQuery().in(MaintainPartsWorkSku::getWorkId,workId).notIn(MaintainPartsWorkSku::getId,partsSkuIds));
						}else {
							partsWorkSkuService.remove(Wrappers.<MaintainPartsWorkSku>lambdaQuery().in(MaintainPartsWorkSku::getWorkId,workId));
						}
						partsWorkSkuService.saveOrUpdateBatch(businessApproveVO.getSkuList());

						// 同步电梯档案位置部件sku信息
						elevatorPartsStructureRelationService.syncElevatorPartsStructureRelation(maintainPlanContent.getId(), maintainPlanContent.getElevatorId());
						// 同步到ERP进行创建采购需求
						// 异步发送 工单id到管理端统一发送到ERP创建采购需求
						ProjectApiConfiguration projectApiConfiguration = SpringUtil.getBean(ProjectApiConfiguration.class);
						if ("592800".equals(AuthUtil.getTenantId()) && isProdEnv()) {
							Long currentPlanId = maintainPlanContent.getId();
							log.warn("========== 发送工单id到管理端统一发送到ERP创建采购需求, planId: {} =========", currentPlanId);
							asyncHttpUtil.createGet(projectApiConfiguration.getWeb() + "/erp/cloud/parts/work/purchase?planId=" + currentPlanId, WebUtil.getRequest());
						}
						break;
					}
				}
				// 驳回
				case REJECT: {
					List<MaintainPartsWork> maintainPartsWorks = maintainPartsWorkService.list(Wrappers.<MaintainPartsWork>lambdaQuery().eq(MaintainPartsWork::getPlanId, maintainPlanContent.getId()));

					businessApprove.setApproveStatus(ApproveStatusEnum.REJECT.getId());
					businessApprove.setRemark(businessApproveVO.getRemark());
					businessApproveService.updateById(businessApprove);
					// 更新工单状态：8->已关闭
					maintainPlanContent.setStatus(TaskStatusEnum.PARTS_CLOSE.getStatus());
					maintainPlanContentService.updateById(maintainPlanContent);
					// 插入任务追踪记录
					String extDesc = JSONObject.toJSONString(MapUtil.ofEntries(MapUtil.entry("approveDesc", ApproveStatusEnum.REJECT.getName()), MapUtil.entry("remark", businessApproveVO.getRemark())));
					malfunctionLogService.insertWorkLog(maintainPlanContent.getId(), TaskStatusEnum.PARTS_CLOSE.getName(), TaskStatusEnum.PARTS_CLOSE.getStatus(), extDesc, AuthUtil.getUserId(), "终止", AuthUtil.getNickName());

					maintainPartsWorks.forEach(e -> {
						e.setImgs(businessApproveVO.getImgs());
					});
					maintainPartsWorkService.updateBatchById(maintainPartsWorks);
					break;
				}
				// 退回
				case RETURN: {
					businessApprove.setApproveStatus(ApproveStatusEnum.RETURN.getId());
					businessApprove.setRemark(businessApproveVO.getRemark());
					businessApproveService.updateById(businessApprove);
					// 插入任务追踪记录
					List<MaintainMalfunctionLog> maintainMalfunctionLogList = malfunctionLogService.list(Wrappers.<MaintainMalfunctionLog>lambdaQuery().eq(MaintainMalfunctionLog::getPlanId, maintainPlanContent.getId()).orderByDesc(MaintainMalfunctionLog::getId));
					MaintainMalfunctionLog maintainMalfunctionLog = null;
					if (Func.isNotEmpty(maintainMalfunctionLogList)) {
						// 更新任务追踪日志
						maintainMalfunctionLog = maintainMalfunctionLogList.get(0);
						maintainMalfunctionLog.setExt(JSONObject.toJSONString(MapUtil.ofEntries(MapUtil.entry("approveDesc", ApproveStatusEnum.RETURN.getName()), MapUtil.entry("remark", businessApproveVO.getRemark()))));
						maintainMalfunctionLog.setUserNames(AuthUtil.getNickName());
						malfunctionLogService.updateById(maintainMalfunctionLog);
					}
					malfunctionLogService.insertWorkLog(maintainPlanContent.getId(), "待处理", TaskStatusEnum.PARTS_APPLY.getStatus(), null, businessApprove.getSubmitId(), businessApprove.getSubmitName());

					//更新审批图片
					List<MaintainPartsWork> maintainPartsWorks = maintainPartsWorkService.list(Wrappers.<MaintainPartsWork>lambdaQuery().eq(MaintainPartsWork::getPlanId, maintainPlanContent.getId()));
					maintainPartsWorks.forEach(e -> {
						e.setImgs(businessApproveVO.getImgs());
					});
					maintainPartsWorkService.updateBatchById(maintainPartsWorks);
					break;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			platformTransactionManager.rollback(transactionStatus);
			throw new ServiceException("审批失败: " + e.getMessage());
		}

		platformTransactionManager.commit(transactionStatus);
		return true;
	}

	@Override
	public boolean reminder(Long businessApproveId) {
		BusinessApprove businessApprove = businessApproveService.getById(businessApproveId);
		if (Func.isEmpty(businessApprove)) {
			throw new ServiceException("未找到相关流程!");
		}
		// 查询工单
		MaintainPlanContent maintainPlanContent = maintainPlanContentService.getById(businessApprove.getWorkOrderId());
		if (maintainPlanContent == null) {
			throw new ServiceException("工单不存在");
		}
		if (businessApprove.getApproveStatus() != ApproveStatusEnum.PENDING.getId() &&
			maintainPlanContent.getStatus() != TaskStatusEnum.PARTS_APPLY.getStatus()) {
			throw new ServiceException("该报障已审批，无需催办!");
		}

		String reminderKey = TemplateMsgConstant.REMINDER_KEY.concat(StringPool.DASH).concat(String.valueOf(businessApproveId));
		long count;
		if (bladeRedis.exists(reminderKey)) {
			count = bladeRedis.incr(reminderKey);
		} else {
			count = bladeRedis.incr(reminderKey);
			bladeRedis.expire(reminderKey, Duration.ofDays(1));
		}

		if (count > 2) {
			throw new ServiceException("您今天的催办次数已经超过上限!");
		}
		return true;
	}

	@Override
	public boolean cancel(Long businessApproveId) {
		BusinessApprove businessApprove = businessApproveService.getById(businessApproveId);
		if (businessApprove == null) {
			throw new ServiceException("审批流程不存在!");
		}
		if (ApproveStatusEnum.PENDING.getId() != businessApprove.getStatus() && ApproveStatusEnum.RETURN.getId() != businessApprove.getStatus()) {
			throw new ServiceException("流程已审批，不能撤回申请");
		}
		if (!Func.equalsSafe(AuthUtil.getUserId(), businessApprove.getSubmitId())) {
			throw new ServiceException("您不是申请人，不能撤回申请");
		}
		businessApprove.setApproveStatus(ApproveStatusEnum.CANCEL.getId());

		// 查询工单
		MaintainPlanContent maintainPlanContent = maintainPlanContentService.getById(businessApprove.getWorkOrderId());
		if (maintainPlanContent == null) {
			throw new ServiceException("工单不存在");
		}
		maintainPlanContent.setStatus(TaskStatusEnum.PARTS_WITHDRAW.getStatus());

		// 手动开启事务
		TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
		try {
			businessApproveService.updateById(businessApprove);
			maintainPlanContentService.updateById(maintainPlanContent);
			// 插入任务追踪日志
			malfunctionLogService.insertWorkLog(maintainPlanContent.getId(), ApproveStatusEnum.CANCEL.getName(), TaskStatusEnum.PARTS_WITHDRAW.getStatus());
		} catch (Exception e) {
			e.printStackTrace();
			platformTransactionManager.rollback(transactionStatus);
			throw new ServiceException("审批失败: " + e.getMessage());
		}

		platformTransactionManager.commit(transactionStatus);
		return true;
	}

	private boolean isProdEnv() {
		String prodEnv = "prod";
		String activeProfile = System.getProperty("spring.profiles.active");
		return prodEnv.equals(activeProfile);
	}
}
